package com.tuling.plugins;

import org.apache.ibatis.cache.CacheKey;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;

/**
 * @author leimingchao
 * create 2024-10-28 19:54
 */
@Intercepts({
        //需要代理的对象和方法
        @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
        @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class})
})
public class MyPageInterceptor implements Interceptor {


    @Override
    public Object intercept(Invocation invocation) throws Throwable {

        System.out.println("简易版的分页插件,逻辑分页改成物理分页");

        //修改sql,拼接limit

        //获取被代理方法的所有参数
        Object[] args = invocation.getArgs();

        for (Object arg : args) {
            System.out.println(arg);
        }

        //MappedStatement对mapper映射文件里面的元素的封装
        MappedStatement mappedStatement = (MappedStatement) args[0];

        //BoundSql对sql和参数的封装
        Object parameterObject = args[1];
        BoundSql boundSql = mappedStatement.getBoundSql(parameterObject);

        //拿到原来的sql语句
        String sql = boundSql.getSql();

        //RowBounds 封装了逻辑分页的参数: 当前页offset, 每页的显示条数limit
        RowBounds rowBounds = (RowBounds) args[2];

        int offset = rowBounds.getOffset();
        int limit = rowBounds.getLimit();

        String limitSql = sql + " limit " + offset + "," + limit;

        //分页的sql重新封装一个BoundSql进行后续执行
        BoundSql pageBoundSql = new BoundSql(mappedStatement.getConfiguration(), limitSql, boundSql.getParameterMappings(), parameterObject);

        //调用被代理的方法
        //return invocation.proceed();


        //被代理的对象
        Executor executor = (Executor) invocation.getTarget();

        CacheKey cacheKey = executor.createCacheKey(mappedStatement, parameterObject, rowBounds, pageBoundSql);
        //使用修改过后的sql调用executor.query()方法
        return executor.query(mappedStatement, parameterObject, rowBounds, (ResultHandler) args[3], cacheKey, pageBoundSql);
    }
}
